package com.zkyt.lib_msdk_ext.component.camera

import com.geoai.mavlink.geoainet.payload.enums.CameraNV2StreamSource
import com.geoai.mavlink.geoainet.payload.enums.CameraNV3StreamSource
import com.geoai.mavlink.geoainet.payload.enums.CameraThermalPalette
import com.geoai.mavlink.geoainet.payload.enums.CameraZoomRatio
import com.geoai.mavlink.geoainet.payload.enums.Thermal2DNoiseMode
import com.geoai.mavlink.geoainet.payload.enums.ThermalFFCMode
import com.geoai.mavlink.geoainet.payload.enums.ThermalImageModel
import com.geoai.mavlink.geoainet.payload.enums.ThermalImageTone
import com.geoai.mavlink.geoainet.payload.interfaces.INV3CameraListener
import com.zkyt.lib_msdk_ext.common.CallbackWithRxHandler
import com.zkyt.lib_msdk_ext.common.SDKExtUtil
import com.zkyt.lib_msdk_ext.common.AutoGetProcessor
import com.zkyt.lib_msdk_ext.component.AbsSDKExt
import com.zkyt.lib_msdk_ext.component.ISDKExt
import io.reactivex.Completable
import io.reactivex.Observable
import io.reactivex.Single
import java.util.Optional

/**
 * Created by chenyu on 2024/1/19
 * Description:
 */
class NV3CameraExt: AbsSDKExt<INV3CameraListener>(), IRealCameraExt, IAdvancedCameraExt {

    private var nv3Camera: INV3CameraListener? = null

    override fun init(originManager: INV3CameraListener) {
        nv3Camera = originManager
    }

    override fun destroy() {
        super.destroy()
        nv3Camera = null
    }

    override fun getOriginManager(): INV3CameraListener? {
        return nv3Camera
    }

    fun setCameraSourceRx(source: CameraNV3StreamSource): Completable {
        return Completable.create { emitter ->
            nv3Camera?.setCameraSource(source) {
                SDKExtUtil.handleError(emitter, it)
            }
        }
    }

    fun getCameraSourceRx(): Single<CameraNV3StreamSource> {
        return Single.create {
            nv3Camera?.getCameraSource(CallbackWithRxHandler(it))
        }
    }

    /**
     * 循环主动get camera source。
     *
     * @return
     * @deprecated 其实CameraZoom也可以通过[BaseCameraExt.getCaptureInfoObservable]中的推送获取.
     * 这里做一个循环get的例，避免有的字段没有推送
     */
    fun getCameraSourceObservable(): Observable<Optional<CameraNV3StreamSource>> {
        val curMethod = object : Any() {}.javaClass.enclosingMethod
        return autoGetProcessor.getAutoGetSubject(curMethod, this::getCameraSourceRx)
    }

    fun getCameraZoomRatioRx(): Single<CameraZoomRatio> {
        return Single.create {
            nv3Camera?.getCameraZoomRatio(CallbackWithRxHandler(it))
        }
    }

    /**
     * 循环主动get zoom ratio
     *
     * @return
     *
     * @deprecated 其实CameraZoom也可以通过[BaseCameraExt.getCaptureInfoObservable]中的推送获取.
     * 这里做一个循环get的例，避免有的字段没有推送
     */
    fun getCameraZoomRatioObservable(): Observable<Optional<CameraZoomRatio>> {
        // todo 加todo引起警觉，注释，前往别使用下面注释这种方式了，固件目前的协议架构不支持短时间连续发送同一个的命令
        // 如果断时间有多个监听者多次getxxxObservable，会导致后面的getxxx会失败。
        /** 请使用[getAutoGetSubject] */
//        return Observable.interval(INTERVAL_GET, TimeUnit.MILLISECONDS)
//            .flatMapSingle {
//                getCameraZoomRatioRx()
//            }.subscribeOn(Schedulers.io())

        val curMethod = object : Any() {}.javaClass.enclosingMethod
        return autoGetProcessor.getAutoGetSubject(curMethod, this::getCameraZoomRatioRx)
    }

    fun setCameraZoomRatioRx(ratio: CameraZoomRatio): Completable {
        return Completable.create { emitter ->
            nv3Camera?.setCameraZoomRatio(ratio) {
                SDKExtUtil.handleError(emitter, it)
            }
        }
    }

    fun setThermalPaletteRx(palette: CameraThermalPalette): Completable {
        return Completable.create { emitter ->
            nv3Camera?.setThermalPalette(palette) {
                SDKExtUtil.handleError(emitter, it)
            }
        }
    }

    fun getThermalPaletteRx(): Single<CameraThermalPalette> {
        return Single.create {
            nv3Camera?.getThermalPalette(CallbackWithRxHandler(it))
        }
    }

    fun stopThermalMeasurementRx(): Completable {
        return Completable.create { emitter ->
            nv3Camera?.stopThermalMeasurement {
                SDKExtUtil.handleError(emitter, it)
            }
        }
    }

    fun singleShootRx(source: CameraNV3StreamSource): Completable {
        return Completable.create { emitter ->
            nv3Camera?.startSingleCapture(source) {
                SDKExtUtil.handleError(emitter, it)
            }
        }
    }

    fun setThermalFFCModeRx(ffcMode: ThermalFFCMode): Completable {
        return Completable.create { emitter ->
            nv3Camera?.setThermalFFCMode(ffcMode) {
                SDKExtUtil.handleError(emitter, it)
            }
        }
    }

    fun getThermalFFCModeRx(): Single<ThermalFFCMode> {
        return Single.create {
            nv3Camera?.getThermalFFCMode(CallbackWithRxHandler(it))
        }
    }

    fun setThermalGainRx(gain: Int): Completable {
        return Completable.create { emitter ->
            nv3Camera?.setThermalGain(gain) {
                SDKExtUtil.handleError(emitter, it)
            }
        }
    }

    fun getThermalGainRx(): Single<Int> {
        return Single.create {
            nv3Camera?.getThermalGain(CallbackWithRxHandler(it))
        }
    }

    fun setThermalNoiseFilterRx(noiseFilter: Thermal2DNoiseMode): Completable {
        return Completable.create { emitter ->
            nv3Camera?.setThermal2DNoiseFilter(noiseFilter) {
                SDKExtUtil.handleError(emitter, it)
            }
        }
    }

    fun getThermalNoiseFilterRx(): Single<Thermal2DNoiseMode> {
        return Single.create {
            nv3Camera?.getThermal2DNoiseFilter(CallbackWithRxHandler(it))
        }
    }

    fun setThermalDebunchingEnableRx(boolean: Boolean): Completable {
        return Completable.create { emitter ->
            nv3Camera?.setThermalDebunchingEnable(boolean) {
                SDKExtUtil.handleError(emitter, it)
            }
        }
    }

    fun getThermalDebunchingEnableRx(): Single<Boolean> {
        return Single.create {
            nv3Camera?.getThermalDebunchingEnable(CallbackWithRxHandler(it))
        }
    }

    fun setThermalImageModelRx(thermalImageModel: ThermalImageModel): Completable {
        return Completable.create { emitter ->
            nv3Camera?.setThermalImageModel(thermalImageModel) {
                SDKExtUtil.handleError(emitter, it)
            }
        }
    }

    fun getThermalImageModelRx(): Single<ThermalImageModel> {
        return Single.create {
            nv3Camera?.getThermalImageModel(CallbackWithRxHandler(it))
        }
    }

    fun setThermalImageToneRx(thermalImageTone: ThermalImageTone): Completable {
        return Completable.create { emitter ->
            nv3Camera?.setThermalImageTone(thermalImageTone) {
                SDKExtUtil.handleError(emitter, it)
            }
        }
    }

    fun getThermalImageToneRx(): Single<ThermalImageTone> {
        return Single.create {
            nv3Camera?.getThermalImageTone(CallbackWithRxHandler(it))
        }
    }

    fun setThermalDistanceRx(distance: Int): Completable {
        return Completable.create { emitter ->
            nv3Camera?.setThermalDistance(distance) {
                SDKExtUtil.handleError(emitter, it)
            }
        }
    }

    fun getThermalDistanceRx(): Single<Int> {
        return Single.create {
            nv3Camera?.getThermalDistance(CallbackWithRxHandler(it))
        }
    }

    fun setThermalEmissivityRx(emissivity: Int): Completable {
        return Completable.create { emitter ->
            nv3Camera?.setThermalEmissivity(emissivity) {
                SDKExtUtil.handleError(emitter, it)
            }
        }
    }

    fun getThermalEmissivityRx(): Single<Int> {
        return Single.create {
            nv3Camera?.getThermalEmissivity(CallbackWithRxHandler(it))
        }
    }
}